from flask import render_template, redirect, url_for, flash, request, jsonify, session, send_file, make_response
from flask_login import login_user, logout_user, login_required, current_user
from flask_mail import Message
from PIL import Image, ImageDraw, ImageFont
import random
import io
from sqlalchemy.exc import IntegrityError
from . import bp
from app.models import User, Movies, Tags, MovieTags, UserTags
from app import db, mail
from app.config import Config
from app.utils.page import Paginator
from app.utils import mongo_operate, recommend as recommend_util
from datetime import datetime
from pymongo import DESCENDING
import time


def generate_code(length=6):
    return ''.join(random.choices('0123456789', k=length))


@bp.route('/send_code', methods=['POST'])
def send_code():
    data = request.get_json()
    email = data.get('email')
    if not email:
        return jsonify({'error': 'email is required'}), 4000
    code = generate_code(8)
    html_content = render_template('mail/verify_code.html', code=code, year=datetime.now().year)
    msg = Message('您的验证码', recipients=[email], html=html_content)
    try:
        mail.send(msg)
        session['verify_code'] = code
        session['verify_email'] = email
        session['verify_time'] = int(time.time())
        return jsonify({"success": True, "message": "验证码发送成功, 有效期5分钟"}), 200
    except Exception as e:
        print(e)
        return jsonify({"error": "验证码发送失败, 请稍后再试"}), 5000


def verify_code(user_code, email):
    if not user_code or not email:
        return False, '缺少参数'

    saved_code = session.get('verify_code')
    saved_email = session.get('verify_email')
    saved_time = session.get('verify_time')

    # 验证是否过期（5分钟 = 300秒）
    if not saved_time or time.time() - saved_time > 300:
        return False, '验证码已过期'

    if saved_code == user_code and saved_email == email:
        return True, '验证通过'
    else:
        return False, '验证码错误'


def generate_captcha():
    # 生成随机字符串
    chars = random.choices(Config.CAPTCHA_RANGE, k=4)
    captcha_text = "".join(chars)

    # 保存到 session（需设置 secret_key）
    session["captcha"] = captcha_text

    # 创建图片
    img = Image.new("RGB", (120, 40), (255, 255, 255))
    draw = ImageDraw.Draw(img)

    # 绘制干扰线
    for _ in range(5):
        draw.line(
            [
                (random.randint(0, 120), random.randint(0, 40)),
                (random.randint(0, 120), random.randint(0, 40)),
            ],
            fill=(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)),
        )

    # 绘制文本
    font = ImageFont.truetype(Config.FONT_PATH, 30)
    draw.text((30, 10), captcha_text, fill=(0, 0, 0), font=font)

    buffer = io.BytesIO()  # 图片二进制
    img.save(buffer, "PNG")
    buffer.seek(0)
    return buffer


def response_success(message):
    return jsonify({"success": True, "message": message})


def response_fail(message, code):
    return jsonify({"error": message}), code


@bp.route("/captcha")
def captcha():
    """返回 Base64 编码的验证码图片"""
    img_buffer = generate_captcha()
    return send_file(img_buffer, mimetype='image/png')


@bp.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        """验证登录信息"""
        user_input = request.form.get("captcha").upper()
        correct_captcha = session.get("captcha", "").upper()
        if user_input != correct_captcha:
            flash("验证码不正确", "warning")
            return redirect(url_for("user.login"))

        username = request.form['username']
        password = request.form['password']
        is_remember = request.form.get('rememberMe') == 'on'
        user = User.query.filter_by(username=username).first()
        if user is None or not user.check_password(password):
            flash('用户名或密码错误', "warning")
            return redirect(url_for('user.login'))
        login_user(user, remember=is_remember)
        return redirect(url_for('user.index'))
    return render_template('user/login.html', title='登录')


@bp.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('user.login'))


@bp.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        username = request.form['username']
        email = request.form['email']
        password = request.form['password']
        passwordAgain = request.form['passwordAgain']
        code = request.form['code']
        status, message = verify_code(code, email)
        if not status:
            flash(message)
            return redirect(url_for('user.reset_password'))
        user = User.query.filter_by(username=username).first()
        if user is not None:
            flash('用户名已存在', "warning")
            return redirect(url_for('user.register'))
        if password != passwordAgain:
            flash("两次密码输入不一致", "warning")
            return redirect(url_for('user.register'))
        new_user = User(username=username, email=email, password=password)
        try:
            db.session.add(new_user)
            db.session.commit()
            flash("注册成功, 请返回登录页登录", "success")
            return redirect(url_for('user.login'))
        except IntegrityError:
            db.session.rollback()
            flash("未知错误, 请稍后重试", "warning")
            return redirect(url_for('user.register'))
    return render_template('user/register.html', title='注册')


@bp.route('/reset_password', methods=['GET', 'POST'])
def reset_password():
    if request.method == 'POST':
        username = request.form['username']
        email = request.form['email']
        password = request.form['password']
        password_again = request.form['password_again']
        code = request.form['code']
        status, message = verify_code(code, email)
        if not status:
            flash(message)
            return redirect(url_for('user.reset_password'))
        user = User.query.filter_by(username=username).first()
        if user is None:
            flash("用户不存在, 请核对后重试", "warning")
            return redirect(url_for('user.reset_password'))
        if password != password_again:
            flash("两次密码输入不一致", "warning")
            return redirect(url_for('user.reset_password'))
        User.set_password(user, password)
        try:
            db.session.add(user)
            db.session.commit()
            flash("重置成功, 请返回登录", "success")
            return redirect(url_for('user.login'))
        except IntegrityError:
            db.session.rollback()
            flash("位置错误, 请稍后重试", "warning")
            return redirect(url_for('user.reset_password'))
    return render_template('user/reset_password.html', title='重置密码')


@bp.route('/', methods=['GET'])
@bp.route('/<int:page>', methods=['GET'])
@login_required
def index(page=1):
    # 获取参数（默认空字符串或 None）
    search = request.args.get('search', '').strip()
    sort = request.args.get('sort', '')

    # 查询基础
    query = Movies.query

    # 搜索过滤
    if search:
        query = query.filter(Movies.name.ilike(f"%{search}%"))

    # 排序处理
    if sort == 'rate_desc':
        query = query.order_by(Movies.rate.desc())
    elif sort == 'rate_asc':
        query = query.order_by(Movies.rate.asc())
    elif sort == 'year_desc':
        query = query.order_by(Movies.years.desc())
    elif sort == 'year_asc':
        query = query.order_by(Movies.years.asc())
    else:
        sort = 'year_desc'  # 默认排序
        query = query.order_by(Movies.years.desc())

    # 分页
    movies = query.all()
    pagination = Paginator(list(movies), page=page, per_page=6)

    # 推荐部分
    recommend = recommend_util.recommend_movies(current_user.id)
    recommend_movies = Movies.query.filter(Movies.id.in_(recommend)).all()

    resp = make_response(render_template(
        'user/index.html',
        title='首页',
        pagination=pagination,
        recommend=recommend_movies,
        sort=sort,
        search=search
    ))
    resp.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0, max-age=0'
    resp.headers['Pragma'] = 'no-cache'
    # 渲染模板
    return resp


@bp.route('/refresh_recommend', methods=['POST'])
@login_required
def refresh_recommend():
    user_id = current_user.id
    movie_ids = recommend_util.recommend_movies(user_id, refresh=True)

    movie_objs = Movies.query.filter(Movies.id.in_(movie_ids)).all()

    recommend_html = render_template('user/components/recommend_block.html', recommend=movie_objs)
    return jsonify({'recommend_html': recommend_html})


@bp.route('/movie/<int:movie_id>', methods=['GET', 'POST'])
@login_required
def movie_detail(movie_id):
    if request.method == 'POST':
        user_rating = request.form['user_rating']
        if user_rating.isdigit() and 1 <= int(user_rating) <= 10:
            mongo_operate.insert_document('score_record', {
                "user_id": current_user.id,
                "user_rating": int(user_rating),
                "movie_id": movie_id,
                "created_at": datetime.now()
            })
        else:
            flash("未知错误, 请稍后重试", "warning")
    movie = Movies.query.filter_by(id=movie_id).first()
    if not movie or movie is None:
        flash("电影不存在", "warning")
        return redirect(url_for('user.index'))
    movie.views += 1
    try:
        db.session.add(movie)
        db.session.commit()
    except IntegrityError:
        db.session.rollback()
        flash('未知错误, 请稍后重试', "warning")
        return redirect(url_for('user.index'))
    mongo_operate.insert_document('browsing_history',
                                  {"user_id": current_user.id,
                                   "movie_id": movie_id,
                                   "created_at": datetime.now()})
    results = list(mongo_operate.find_documents('score_record',
                                                {"user_id": current_user.id, "movie_id": movie_id},
                                                sort=[("created_at", DESCENDING)]))
    user_rating = results[0]["user_rating"] if results else None
    return render_template('user/movie_detail.html', title='电影详情', movie=movie, user_rating=user_rating)


@bp.route('/tags', methods=['GET', 'POST'])
@login_required
def tags():
    if request.method == 'POST':
        data = request.get_json()
        selectedTags = data.get("selectedTags")
        if len(selectedTags) == 0:
            return response_fail("未选择标签", 4000)

        # 查询当前用户是否已在 UserTags 表中存在记录
        existing_tags = UserTags.query.filter_by(user_id=current_user.id).all()
        if existing_tags:
            # 如果存在，删除所有当前用户的标签记录
            for tag in existing_tags:
                db.session.delete(tag)
            db.session.commit()
        for tag in selectedTags:
            tag_o = Tags.query.filter_by(name=tag).first()
            userTags = UserTags(current_user.id, tag_o.id)
            try:
                db.session.add(userTags)
                db.session.commit()
            except IntegrityError:
                db.session.rollback()
                return response_fail("未知错误, 请稍后再试", 5000)
        return response_success("标签选择成功")
    tag_list = Tags.query.all()
    return render_template('user/tags.html', title='标签', tags=tag_list)
